#pragma once
#include "stdafx.h"

const int g_iVersion = 1; // version of coclasses.

static const char *g_szProgIDPrefix   = "My Profiler";
static const char *g_szThreadingModel = "Both";
static const char *g_szCoclassDesc    = "My Profiler";

typedef HRESULT (__stdcall * PFN_CREATE_OBJ)( REFIID riid, void **ppInterface );

struct COCLASS_REGISTER
{   
	const GUID *pClsid;             // Class ID of the coclass
	const char *szProgID;           // Prog ID of the class
	PFN_CREATE_OBJ pfnCreateObject; // function to create instance
};

class CClassFactory :
	public IClassFactory
{
private:

	CClassFactory();                        


public:

	CClassFactory( const COCLASS_REGISTER *pCoClass );
	~CClassFactory();

public:

	//
	// IUnknown 
	//
	ULONG STDMETHODCALLTYPE AddRef();       
	ULONG STDMETHODCALLTYPE Release();
	HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void **ppInterface );            

	//
	// IClassFactory 
	//
	HRESULT STDMETHODCALLTYPE LockServer( BOOL fLock );
	HRESULT STDMETHODCALLTYPE CreateInstance( IUnknown *pUnkOuter,
		REFIID riid,
		void **ppInterface );


private:

	long m_refCount;                        
	const COCLASS_REGISTER *m_pCoClass;     

};

CClassFactory::CClassFactory()
{    
} 

CClassFactory::CClassFactory( const COCLASS_REGISTER *pCoClass ) :
	m_refCount( 1 ), 
	m_pCoClass( pCoClass )
{    
}

CClassFactory::~CClassFactory()
{
} 

ULONG CClassFactory::AddRef()
{
	return InterlockedIncrement( &m_refCount );
}

ULONG CClassFactory::Release()
{    
	long refCount;

	refCount = InterlockedDecrement( &m_refCount );
	if ( refCount == 0 ) 
		delete this;

	return refCount;   
} 

HRESULT CClassFactory::QueryInterface( REFIID riid, void **ppInterface )
{    
	if ( riid == IID_IUnknown )
		*ppInterface = static_cast<IUnknown *>( this ); 

	else if ( riid == IID_IClassFactory )
		*ppInterface = static_cast<IClassFactory *>( this );

	else
	{
		*ppInterface = NULL;                  

		return E_NOINTERFACE;
	}

	reinterpret_cast<IUnknown *>( *ppInterface )->AddRef();

	return S_OK;
}

HRESULT CClassFactory::CreateInstance( IUnknown *pUnkOuter, REFIID riid, void **ppInstance )
{       
	// aggregation is not supported by these objects
	if ( pUnkOuter != NULL )
		return CLASS_E_NOAGGREGATION;


	// ask the object to create an instance of itself, and check the iid.
	return (*m_pCoClass->pfnCreateObject)( riid, ppInstance );

} 

HRESULT CClassFactory::LockServer( BOOL fLock )
{    
	//
	// we are not required to hook any logic since this is always
	// and in-process server, we define the method for completeness
	//
	return S_OK;
}
